
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTTP + SSE + RAG 聊天演示</title>
    <style>
        /* 保留原有所有样式 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background-color: #f0f2f5;
            color: #333;
            line-height: 1.6;
            display: flex;
            flex-direction: column;
            min-height: 100vh;
        }
        
        header {
            background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
            color: white;
            padding: 1rem;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            position: relative;
            overflow: hidden;
        }
        
        .header-content {
            max-width: 1200px;
            margin: 0 auto;
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: relative;
            z-index: 2;
        }
        
        .logo {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .logo-icon {
            font-size: 2rem;
            background: rgba(255, 255, 255, 0.15);
            width: 50px;
            height: 50px;
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .connection-status {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 8px 15px;
            background: rgba(255, 255, 255, 0.15);
            border-radius: 20px;
            font-size: 0.85rem;
        }
        
        .status-indicator {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            display: inline-block;
        }
        
        .connected .status-indicator {
            background-color: #4caf50;
            box-shadow: 0 0 8px #4caf50;
        }
        
        .disconnected .status-indicator {
            background-color: #f44336;
        }
        
        .container {
            max-width: 1200px;
            margin: 20px auto;
            padding: 0 20px;
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
        }
        
        .chat-container {
            flex: 1;
            min-width: 300px;
            background-color: white;
            border-radius: 12px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
            overflow: hidden;
            display: flex;
            flex-direction: column;
        }
        
        .chat-header {
            background-color: #2c3e50;
            color: white;
            padding: 15px 20px;
            font-size: 1.1rem;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .chat-box {
            flex: 1;
            padding: 20px;
            overflow-y: auto;
            max-height: 60vh;
            min-height: 300px;
            background-color: #f9f9f9;
            position: relative;
            scroll-behavior: smooth;
        }
        
        .message {
            margin-bottom: 15px;
            padding: 12px 16px;
            border-radius: 18px;
            max-width: 85%;
            line-height: 1.5;
            position: relative;
            animation: fadeIn 0.3s ease;
            clear: both;
        }
        
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }
        
        .user-message {
            background-color: #0084ff;
            color: white;
            float: right;
            border-bottom-right-radius: 4px;
        }
        
        .ai-message {
            background-color: #f0f0f0;
            float: left;
            border-bottom-left-radius: 4px;
            color: #333;
        }
        
        .input-area {
            padding: 15px;
            background-color: #fff;
            border-top: 1px solid #eee;
            display: flex;
            gap: 10px;
        }
        
        #user-input {
            flex: 1;
            padding: 12px 16px;
            border: 1px solid #ddd;
            border-radius: 24px;
            outline: none;
            font-size: 1rem;
            transition: border-color 0.3s;
        }
        
        #user-input:focus {
            border-color: #0084ff;
            box-shadow: 0 0 0 2px rgba(0, 132, 255, 0.2);
        }
        
        #send-button {
            background-color: #0084ff;
            color: white;
            border: none;
            width: 48px;
            height: 48px;
            border-radius: 50%;
            font-size: 1.1rem;
            cursor: pointer;
            transition: background-color 0.2s;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        #send-button:hover {
            background-color: #0073e6;
        }
        
        .typing-indicator {
            display: none;
            padding: 12px 16px;
            background-color: #f0f0f0;
            border-radius: 18px;
            max-width: 120px;
            margin-bottom: 15px;
            float: left;
            animation: fadeIn 0.3s ease;
        }
        
        .typing-indicator span {
            height: 8px;
            width: 8px;
            background-color: #aaa;
            border-radius: 50%;
            display: inline-block;
            margin-right: 4px;
            animation: bounce 1.5s infinite;
        }
        
        .typing-indicator span:nth-child(2) {
            animation-delay: 0.2s;
        }
        
        .typing-indicator span:nth-child(3) {
            animation-delay: 0.4s;
        }
        
        @keyframes bounce {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-5px); }
        }
        
        .error-message {
            display: none;
            background-color: #ffebee;
            color: #c62828;
            padding: 12px 16px;
            border-radius: 8px;
            margin: 10px 0;
            text-align: center;
            animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both;
        }
        
        @keyframes shake {
            10%, 90% { transform: translateX(-1px); }
            20%, 80% { transform: translateX(2px); }
            30%, 50%, 70% { transform: translateX(-4px); }
            40%, 60% { transform: translateX(4px); }
        }
        
        .placeholder {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: #aaa;
            font-size: 1.1rem;
            text-align: center;
            width: 100%;
            padding: 0 20px;
        }
        
        .features {
            flex: 1;
            min-width: 280px;
            background-color: white;
            border-radius: 12px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
            padding: 25px;
            height: fit-content;
        }
        
        .features h2 {
            color: #2c3e50;
            margin-bottom: 20px;
            padding-bottom: 10px;
            border-bottom: 1px solid #eee;
        }
        
        .features ul {
            list-style: none;
        }
        
        .features li {
            padding: 12px 0;
            border-bottom: 1px solid #f0f0f0;
            display: flex;
            align-items: center;
            gap: 12px;
        }
        
        .features li::before {
            content: "✓";
            color: #0084ff;
            font-weight: bold;
            font-size: 1.3rem;
        }
        
        .footer {
            margin-top: auto;
            background-color: #2c3e50;
            color: rgba(255, 255, 255, 0.7);
            padding: 20px;
            text-align: center;
            font-size: 0.9rem;
        }
        
        .code-header {
            background-color: #2c3e50;
            color: white;
            padding: 15px 20px;
            border-radius: 12px 12px 0 0;
            margin: 40px 0 0;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .code-block {
            background-color: #1e1e1e;
            color: #d4d4d4;
            border-radius: 0 0 12px 12px;
            padding: 20px;
            overflow-x: auto;
            font-family: 'Courier New', monospace;
            line-height: 1.5;
            font-size: 0.95rem;
        }
        
        .code-tag {
            color: #9cdcfe;
        }
        
        .code-keyword {
            color: #c586c0;
        }
        
        .code-function {
            color: #dcdcaa;
        }
        
        .code-comment {
            color: #6a9955;
        }
        
        .code-string {
            color: #ce9178;
        }
        
        .code-constant {
            color: #569cd6;
        }
        
        @media (max-width: 768px) {
            .container {
                flex-direction: column;
            }
            
            .chat-box {
                max-height: 50vh;
            }
        }
        
        .typewriter-container {
            position: relative;
            display: inline-block;
        }
        
        .typewriter-text {
            display: inline;
            position: relative;
        }
        
        .typewriter-cursor {
            display: inline-block;
            width: 8px;
            height: 1.2em;
            background-color: #3498db;
            margin-left: 2px;
            animation: blink 1s infinite;
            vertical-align: bottom;
        }
        
        @keyframes blink {
            0%, 100% { opacity: 1; }
            50% { opacity: 0; }
        }
        
        .protocol-switcher {
            display: flex;
            background: rgba(255, 255, 255, 0.15);
            border-radius: 50px;
            padding: 5px;
            margin-top: 15px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            backdrop-filter: blur(10px);
            position: relative;
            overflow: hidden;
        }
        
        .protocol-btn {
            position: relative;
            z-index: 1;
            background: transparent;
            color: rgba(255, 255, 255, 0.8);
            border: none;
            padding: 10px 25px;
            border-radius: 50px;
            cursor: pointer;
            font-weight: 500;
            transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
            font-size: 0.95rem;
        }
        
        .protocol-btn.active {
            color: white;
            font-weight: 600;
        }
        
        .protocol-btn:hover:not(.active) {
            background: rgba(255, 255, 255, 0.1);
        }
        
        .protocol-indicator {
            position: absolute;
            top: 5px;
            bottom: 5px;
            left: 5px;
            width: calc(50% - 5px);
            background: linear-gradient(135deg, #3498db 0%, #2c3e50 100%);
            border-radius: 50px;
            z-index: 0;
            transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }
        
        .protocol-btn i {
            font-size: 1.2rem;
        }
        
        .sse-active .protocol-indicator {
            transform: translateX(100%);
        }
        
        /* 图标样式 */
        .http-icon::before {
            content: "🌐";
            margin-right: 5px;
        }
        
        .sse-icon::before {
            content: "⚡";
            margin-right: 5px;
        }
        
        /* 新增文件上传区域样式 */
        .upload-area {
            background-color: white;
            border-radius: 12px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
            padding: 20px;
            margin-top: 20px;
        }
        
        .upload-btn {
            background-color: #9c27b0;
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 24px;
            cursor: pointer;
            font-size: 1rem;
            transition: background-color 0.3s;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .upload-btn:hover {
            background-color: #7b1fa2;
        }
        
        .file-info {
            margin-top: 15px;
            padding: 10px;
            background-color: #f5f5f5;
            border-radius: 8px;
            display: none;
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- 文件上传区域 (RAG知识库增强) -->
        <div class="upload-area">
            <h2>知识库上传</h2>
            <p>上传文件到向量数据库，增强AI的知识库</p>
            <input type="file" id="file-input" accept=".txt,.pdf,.docx,.pptx" style="display:none">
            <button class="upload-btn" id="upload-button">
                <i class="upload-icon">📁</i> 选择文件
            </button>
            <div id="file-info" class="file-info">
                <p>已选择: <span id="file-name">-</span></p>
                <p>文件类型: <span id="file-type">-</span></p>
                <p>文件大小: <span id="file-size">-</span></p>
                <button id="upload-action" class="upload-btn" style="background-color:#2196f3; margin-top:10px">
                    <i class="upload-icon">🚀</i> 上传到知识库
                </button>
                <div id="upload-status" style="margin-top:15px;"></div>
            </div>
        </div>
        
        <header>
            <h1>HTTP + SSE + RAG 聊天演示</h1>
            <p>本页面展示了HTTP/SSE协议与RAG增强的聊天交互</p>
            <div class="protocol-selector">
                <button class="protocol-btn active" id="http-btn">HTTP协议</button>
                <button class="protocol-btn" id="sse-btn">SSE协议</button>
            </div>
        </header>
        
        <div class="chat-container">
            <div class="chat-header">
                <span>聊天面板</span>
                <div class="status-indicator">
                    <div class="status-dot" id="status-dot"></div>
                    <span id="status-text">正在连接...</span>
                </div>
            </div>
            
            <div class="chat-box" id="chat-box">
                <div id="typing-indicator" class="typing-indicator">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                
                <div class="message ai-message">
                    您好！请选择上方的协议类型开始聊天。HTTP协议是传统的请求-响应模式，SSE协议支持实时流式响应。
                </div>
            </div>
            
            <div class="input-area">
                <input type="text" id="user-input" placeholder="输入您的问题...">
                <button id="send-button">➤</button>
            </div>
        </div>
        
        <div class="instructions">
            <h2>使用说明</h2>
            <p>本演示展示了两种不同的通信协议：</p>
            
            <ul>
                <li><strong>HTTP协议</strong>：传统的请求-响应模式，发送消息后等待完整响应</li>
                <li><strong>SSE协议</strong>：服务器推送事件模式，支持实时流式响应</li>
                <li><strong>RAG技术</strong>：通过上传文件增强AI的知识库，提高回答准确性</li>
            </ul>
            
            <p>使用步骤：</p>
            <ol>
                <li>选择上方的协议类型（HTTP或SSE）</li>
                <li>在输入框中输入您的问题</li>
                <li>点击发送按钮或按Enter键</li>
                <li>观察不同协议下的响应方式</li>
                <li>上传文件增强AI知识库（支持TXT/PDF/DOCX/PPTX）</li>
            </ol>
            
            <p><strong>SSE协议特点</strong>：</p>
            <ul>
                <li>实时接收部分响应，无需等待完整结果</li>
                <li>支持"打字机"效果，提升用户体验</li>
                <li>减少网络请求次数</li>
                <li>更适合长文本生成场景</li>
            </ul>
        </div>
        
        <div class="code-container">
            <div class="code-header">
                <h3>SSE连接核心代码</h3>
                <div>使用EventSource API建立连接</div>
            </div>
            <div class="code-block">
                <span class="code-comment">// 创建SSE连接</span><br>
                <span class="code-keyword">function</span> <span class="code-function">connectSSE</span>() {<br>
                &nbsp;&nbsp;<span class="code-keyword">const</span> eventSource = <span class="code-keyword">new</span> EventSource(<span class="code-string">'/api/chat_stream'</span>);<br><br>
                
                &nbsp;&nbsp;<span class="code-comment">// 监听消息事件</span><br>
                &nbsp;&nbsp;eventSource.onmessage = <span class="code-keyword">function</span>(event) {<br>
                &nbsp;&nbsp;&nbsp;&nbsp;<span class="code-keyword">const</span> data = JSON.parse(event.data);<br>
                &nbsp;&nbsp;&nbsp;&nbsp;<span class="code-keyword">if</span> (data.event === <span class="code-string">'message'</span>) {<br>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-comment">// 处理部分响应</span><br>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;updateChat(data.data, <span class="code-keyword">false</span>);<br>
                &nbsp;&nbsp;&nbsp;&nbsp;}<br>
                &nbsp;&nbsp;&nbsp;&nbsp;<span class="code-keyword">else if</span> (data.event === <span class="code-string">'complete'</span>) {<br>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-comment">// 完成响应</span><br>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hideTypingIndicator();<br>
                &nbsp;&nbsp;&nbsp;&nbsp;}<br>
                &nbsp;&nbsp;};<br><br>
                
                &nbsp;&nbsp;<span class="code-comment">// 错误处理</span><br>
                &nbsp;&nbsp;eventSource.onerror = <span class="code-keyword">function</span>() {<br>
                &nbsp;&nbsp;&nbsp;&nbsp;updateStatus(<span class="code-string">'连接中断'</span>, <span class="code-string">'#e74c3c'</span>);<br>
                &nbsp;&nbsp;&nbsp;&nbsp;eventSource.close();<br>
                &nbsp;&nbsp;};<br>
                }<br><br>
            </div>
        </div>
    </div>

    <script>
        // ====== DOM元素引用 ======
        const chatBox = document.getElementById('chat-box');
        const userInput = document.getElementById('user-input');
        const sendButton = document.getElementById('send-button');
        const typingIndicator = document.getElementById('typing-indicator');
        const statusDot = document.getElementById('status-dot');
        const statusText = document.getElementById('status-text');
        const httpBtn = document.getElementById('http-btn');
        const sseBtn = document.getElementById('sse-btn');
        const protocolSwitcher = document.querySelector('.protocol-switcher');
        
        // 文件上传相关DOM
        let selectedFile = null;
        const fileInput = document.getElementById('file-input');
        const uploadButton = document.getElementById('upload-button');
        const fileInfo = document.getElementById('file-info');
        const fileName = document.getElementById('file-name');
        const fileType = document.getElementById('file-type');
        const fileSize = document.getElementById('file-size');
        const uploadAction = document.getElementById('upload-action');
        const uploadStatus = document.getElementById('upload-status');

        // 全局变量
        let currentProtocol = 'http';
        let eventSource = null;
        let sessionId = null;
        let currentAiMessage = null;
        let typewriterInterval = null;

        // ====== 通用功能函数 ======
        // 更新状态指示器
        function updateStatus(text, color) {
            statusText.textContent = text;
            statusDot.style.backgroundColor = color;
            statusDot.classList.toggle('connected', color === '#2ecc71');
        }

        // 添加消息到聊天框
        function addMessage(content, isUser = false, useTypewriter = false) {
            const messageDiv = document.createElement('div');
            messageDiv.classList.add('message');
            messageDiv.classList.add(isUser ? 'user-message' : 'ai-message');
            
            if (isUser) {
                messageDiv.textContent = '您: ' + content;
            } else {
                if (useTypewriter) {
                    const typewriterContainer = document.createElement('div');
                    typewriterContainer.classList.add('typewriter-container');
                    
                    const typewriterText = document.createElement('span');
                    typewriterText.classList.add('typewriter-text');
                    typewriterText.textContent = 'AI: ';
                    
                    const cursor = document.createElement('span');
                    cursor.classList.add('typewriter-cursor');
                    
                    typewriterContainer.appendChild(typewriterText);
                    typewriterContainer.appendChild(cursor);
                    messageDiv.appendChild(typewriterContainer);
                } else {
                    messageDiv.textContent = 'AI: ' + content;
                }
            }
            
            chatBox.appendChild(messageDiv);
            chatBox.scrollTop = chatBox.scrollHeight;
            return messageDiv;
        }

        // 显示/隐藏"正在输入"状态
        function showTypingIndicator() {
            typingIndicator.style.display = 'flex';
            chatBox.scrollTop = chatBox.scrollHeight;
        }

        function hideTypingIndicator() {
            typingIndicator.style.display = 'none';
        }

        // 打字机效果函数
        function typewriterEffect(element, text, speed = 50) {
            if (typewriterInterval) {
                clearInterval(typewriterInterval);
                typewriterInterval = null;
            }
            
            let i = 0;
            const textSpan = element.querySelector('.typewriter-text');
            const cursor = element.querySelector('.typewriter-cursor');
            
            textSpan.textContent = 'AI: ';
            
            typewriterInterval = setInterval(() => {
                if (i < text.length) {
                    textSpan.textContent += text.charAt(i);
                    i++;
                    chatBox.scrollTop = chatBox.scrollHeight;
                } else {
                    clearInterval(typewriterInterval);
                    typewriterInterval = null;
                    
                    if (cursor) {
                        cursor.style.display = 'none';
                    }
                }
            }, speed);
        }

        // 生成会话ID
        function generateSessionId() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                const r = Math.random() * 16 | 0;
                const v = c === 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        }

        // 格式化文件大小
        function formatFileSize(bytes) {
            if (bytes === 0) return '0 Bytes';
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        // ====== 聊天功能 ======
        // HTTP协议发送消息
        async function sendMessageHTTP() {
            const message = userInput.value.trim();
            if (!message) return;
            
            addMessage(message, true);
            userInput.value = '';
            showTypingIndicator();
            
            try {
                const response = await fetch('/api/chat', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ 
                        user_input: message,
                        use_rag: true // RAG增强
                    })
                });
                
                if (!response.ok) {
                    throw new Error(`请求失败: HTTP ${response.status}`);
                }
                
                const data = await response.json();
                addMessage(data.response, false, false);
            } catch (error) {
                addMessage(`请求错误: ${error.message}`, false, false);
            } finally {
                hideTypingIndicator();
            }
        }

        // SSE协议发送消息
        async function sendMessageSSE() {
            const message = userInput.value.trim();
            if (!message) return;
            
            addMessage(message, true);
            userInput.value = '';
            showTypingIndicator();
            
            if (eventSource) {
                eventSource.close();
                eventSource = null;
            }
            
            if (!sessionId) {
                sessionId = generateSessionId();
            }
            
            // 包含RAG参数
            const url = `/api/chat_stream?user_input=${encodeURIComponent(message)}&session_id=${sessionId}&use_rag=true`;
            eventSource = new EventSource(url);
            
            updateStatus('正在连接...', '#f39c12');
            
            currentAiMessage = addMessage('', false, true);
            let fullResponse = '';
            
            eventSource.onopen = () => {
                updateStatus('已连接，等待响应...', '#2ecc71');
            };
            
            eventSource.onmessage = (event) => {
                try {
                    const data = JSON.parse(event.data);
                    
                    if (data.event === 'status') {
                        updateStatus(data.data, '#f39c12');
                    } 
                    else if (data.event === 'message') {
                        fullResponse += data.data;
                        typewriterEffect(currentAiMessage, fullResponse);
                    }
                    else if (data.event === 'complete') {
                        updateStatus('响应完成', '#2ecc71');
                        hideTypingIndicator();
                        eventSource.close();
                        eventSource = null;
                        currentAiMessage = null;
                    }
                    else if (data.event === 'error') {
                        addMessage(`错误: ${data.data}`, false, false);
                        hideTypingIndicator();
                        eventSource.close();
                        eventSource = null;
                        currentAiMessage = null;
                        updateStatus('连接错误', '#e74c3c');
                    }
                } catch (e) {
                    console.error('解析事件数据失败:', e);
                    if (currentAiMessage) {
                        fullResponse += event.data;
                        typewriterEffect(currentAiMessage, fullResponse);
                    }
                }
            };
            
            eventSource.onerror = (error) => {
                console.error('SSE连接错误:', error);
                updateStatus('连接中断', '#e74c3c');
                hideTypingIndicator();
                eventSource.close();
                eventSource = null;
                currentAiMessage = null;
            };
        }

        // 发送消息（根据当前协议）
        function sendMessage() {
            if (currentProtocol === 'http') {
                sendMessageHTTP();
            } else {
                sendMessageSSE();
            }
        }

        // ====== 文件上传功能 ======
        // 文件选择处理
        uploadButton.addEventListener('click', () => fileInput.click());
        
        fileInput.addEventListener('change', function() {
            if (this.files.length === 0) return;
            
            selectedFile = this.files[0];
            fileName.textContent = selectedFile.name;
            fileType.textContent = selectedFile.type || '未知类型';
            fileSize.textContent = formatFileSize(selectedFile.size);
            fileInfo.style.display = 'block';
        });
        
        // 文件上传到后端处理
        uploadAction.addEventListener('click', async () => {
            if (!selectedFile) return;
            
            uploadStatus.textContent = "上传中，请稍候...";
            uploadStatus.style.color = "#2196f3";
            uploadAction.disabled = true;
            
            try {
                const formData = new FormData();
                formData.append('file', selectedFile);
                
                const response = await fetch('/api/upload', {
                    method: 'POST',
                    body: formData
                });
                
                if (!response.ok) {
                    throw new Error(`上传失败: HTTP ${response.status}`);
                }
                
                const result = await response.json();
                
                if (result.status === 'success') {
                    uploadStatus.innerHTML = `✅ 上传成功!<br>已处理 ${result.segments_inserted} 个文本片段`;
                    uploadStatus.style.color = "#4caf50";
                    addMessage(`已成功上传文件 "${selectedFile.name}" 到知识库`, false);
                } else {
                    throw new Error(result.message || '上传失败');
                }
            } catch (error) {
                uploadStatus.textContent = `❌ 错误: ${error.message}`;
                uploadStatus.style.color = "#f44336";
                console.error('上传错误:', error);
            } finally {
                uploadAction.disabled = false;
            }
        });

        // ====== 协议切换功能 ======
        httpBtn.addEventListener('click', () => {
            currentProtocol = 'http';
            httpBtn.classList.add('active');
            sseBtn.classList.remove('active');
            protocolSwitcher.classList.remove('sse-active');
            updateStatus('HTTP模式', '#3498db');
            
            if (eventSource) {
                eventSource.close();
                eventSource = null;
            }
            currentAiMessage = null;
        });

        sseBtn.addEventListener('click', () => {
            currentProtocol = 'sse';
            sseBtn.classList.add('active');
            httpBtn.classList.remove('active');
            protocolSwitcher.classList.add('sse-active');
            updateStatus('SSE模式（发送消息时建立连接）', '#3498db');
            
            if (eventSource) {
                eventSource.close();
                eventSource = null;
            }
            currentAiMessage = null;
        });

        // ====== 事件监听器 ======
        sendButton.addEventListener('click', sendMessage);
        userInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') sendMessage();
        });

        // 初始化
        updateStatus('请选择协议', '#3498db');
    </script>
</body>
</html>
